/**
 该文件是 uni-app 项目自定义的权限拦截插件，主要用于：
 * 1. 路由权限校验（判断页面是否需要登录、是否有访问权限）
 * 2. 拦截所有页面跳转 API（如 navigateTo、redirectTo、reLaunch、switchTab），在跳转前做权限判断
 * 3. 未登录或无权限时自动跳转到登录页或 404 页
 */
import {
  ERROR404_PATH,
  isPathExists,
  LOGIN_PATH,
  removeQueryString,
  routes,
} from '@/router';
import { isLogin } from '@/utils/auth';

// 白名单路由
const whiteList = ['/'];
routes.forEach((item) => {
  // routes中needLogin属性，用于标识该路由是否需要登录权限才能访问。
  if (item.needLogin !== true) {
    whiteList.push(item.path);
  }
});

/**
 * 权限校验
 * @param {string} path
 * @returns {boolean} 是否有权限
 */
// 判断当前路由是否有访问权限
export function hasPerm(path = '') {
  if (!isPathExists(path) && path !== '/') {
    uni.redirectTo({
      url: ERROR404_PATH,
    });
    return false;
  }
  // 在白名单中或有token，直接放行
  const hasPermission
    = whiteList.includes(removeQueryString(path)) || isLogin();
  if (!hasPermission) {
    // 跳转到登录页面
    // 并将用户的目标路径传递过去，这样可以实现用户登录之后，直接跳转到目标页面
    uni.redirectTo({
      url: `${LOGIN_PATH}?redirect=${encodeURIComponent(path)}`,
    });
  }
  return hasPermission;
}
// 页面跳转 API 拦截
function setupPermission() {
  // 注意：拦截uni.switchTab本身没有问题。但是在微信小程序端点击tabbar的底层逻辑并不是触发uni.switchTab。
  // 所以误认为拦截无效，此类场景的解决方案是在tabbar页面的页面生命周期onShow中处理。
  ['navigateTo', 'redirectTo', 'reLaunch', 'switchTab'].forEach((item) => { //  是 UniApp 提供的页面跳转 API 的名称。
    // https://uniapp.dcloud.net.cn/api/interceptor.html
    uni.addInterceptor(item, {
      // 页面跳转前进行拦截, invoke根据返回值进行判断是否继续执行跳转
      invoke(args) {
        // args为所拦截api中的参数，比如拦截的是uni.redirectTo(OBJECT)，则args对应的是OBJECT参数
        return hasPerm(args.url);
      },
    });
  });
}
// 每个名称对应一个页面跳转方法：
// navigateTo: 跳转到非 tabBar 页面，保留当前页面。
// redirectTo: 跳转到非 tabBar 页面，关闭当前页面。
// reLaunch: 关闭所有页面并跳转到指定页面。
// switchTab: 跳转到 tabBar 页面。

/*
uni.addInterceptor 是 UniApp 提供的 API，用于拦截指定方法的调用。拦截器可以在方法调用前或调用后执行自定义逻辑。
invoke:
在方法调用前执行。
根据返回值决定是否继续执行原方法。
 */

export default setupPermission;
